/*
 * @copyright 2010 Gerald Jacobson
 * @license GNU General Public License
 * 
 * This file is part of Descent Assistant.
 *
 * Descent Assistant is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Descent Assistant is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Descent Assistant.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.amphiprion.descenttool.adapter;

import java.util.ArrayList;
import java.util.List;

import org.amphiprion.descenttool.entity.AvailableMonster;

import android.content.Context;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.ListView;

/**
 * @author Amphiprion
 * 
 */
public class AvailableMonsterAdapter extends ArrayAdapter<AvailableMonster> {
	private List<AvailableMonster> mOriginalValues;
	private List<AvailableMonster> mObjects;
	private NameFilter mFilter;
	private ListView lstMonsters;

	public AvailableMonsterAdapter(Context context, ListView lstMonsters, List<AvailableMonster> monsters) {
		super(context, android.R.layout.simple_list_item_multiple_choice, monsters);
		mOriginalValues = monsters;
		mObjects = monsters;
		this.lstMonsters = lstMonsters;
	}

	@Override
	public Filter getFilter() {
		if (mFilter == null) {
			mFilter = new NameFilter();
		}

		return mFilter;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getCount() {
		return mObjects.size();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public AvailableMonster getItem(int position) {
		return mObjects.get(position);
	}

	/**
	 * Returns the position of the specified item in the array.
	 * 
	 * @param item
	 *            The item to retrieve the position of.
	 * 
	 * @return The position of the specified item.
	 */
	@Override
	public int getPosition(AvailableMonster item) {
		return mObjects.indexOf(item);
	}

	private class NameFilter extends Filter {

		@Override
		protected FilterResults performFiltering(CharSequence prefix) {
			FilterResults results = new FilterResults();

			if (prefix == null || prefix.length() == 0) {
				ArrayList<AvailableMonster> list = new ArrayList<AvailableMonster>(mOriginalValues);
				results.values = list;
				results.count = list.size();
			} else {
				String type = prefix.toString().substring(0, 1);
				String prefixString = prefix.toString().substring(2).toLowerCase().trim();

				final List<AvailableMonster> values = mOriginalValues;
				final int count = values.size();

				final List<AvailableMonster> newValues = new ArrayList<AvailableMonster>(count);

				for (int i = 0; i < count; i++) {
					final AvailableMonster value = values.get(i);
					final String valueText = value.toString().toLowerCase();

					// First match against the whole, non-splitted value
					if (prefixString.length() == 0 || valueText.contains(prefixString)) {
						if ("A".equals(type) || "C".equals(type) && value.extend != null || "M".equals(type) && value.extend == null || "H".equals(type) && value.extend == null
								&& "humanoid".equals(value.clazz) || "B".equals(type) && value.extend == null && "beast".equals(value.clazz) || "E".equals(type)
								&& value.extend == null && "eldritch".equals(value.clazz) || "L".equals(type) && value.extend == null && "lieutenant".equals(value.clazz)) {
							newValues.add(value);
						}
					}
				}

				results.values = newValues;
				results.count = newValues.size();
			}

			return results;
		}

		@SuppressWarnings("unchecked")
		@Override
		protected void publishResults(CharSequence constraint, FilterResults results) {
			mObjects = (List<AvailableMonster>) results.values;
			if (results.count > 0) {
				notifyDataSetChanged();
			} else {
				notifyDataSetInvalidated();
			}
			applyChecked(lstMonsters);
		}
	}

	private void applyChecked(ListView lstMonsters) {

		for (int i = 0; i < mObjects.size(); i++) {
			lstMonsters.setItemChecked(i, mObjects.get(i).checked);
		}
	}
}
